﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.MediaCenter;
using Microsoft.MediaCenter.Hosting;
using Microsoft.MediaCenter.UI;
using Microsoft.WindowsAPICodePack.Shell;
using System.Diagnostics;
using ClipShow2.LibraryManager;
using ClipShow2.MediaFinder;
using ClipShow2.MediaTypes;
using ClipShow2.Storage;
using System.Threading;

namespace ClipShowShell.Code
{
    public class ThumbnailFind
    {
        private string[] _thumbNails;
        private string _thumbNailDir;
        private string _startupMessage = "Starting clipShow, please wait...";
        public ThumbnailFind()
        {
            try
            {
                StorageEngine.Initialize();
                _thumbNailDir = StorageEngine.GetThumbnailDir();
                GrabThumbNails();
            }
            catch
            {
                _thumbNails = new string[0];
                _thumbNails[0] = "";
            }
        }

        private void GrabThumbNails()
        {
            if (Directory.Exists(_thumbNailDir))
            {
                _thumbNails = Directory.GetFiles(_thumbNailDir, "*.jpg", SearchOption.AllDirectories);
            }
            else
            {
                _thumbNails = new string[0];
                _thumbNails[0] = "";
            }
        }
        public string StartupMessage
        {
            get { return (_startupMessage); }
        }
        public Image RandomThumbnail
        {
            get
            {
                if (_thumbNails.Length > 0)
                {
                    string result = GetThumbnailFilePath();
                    if (result.Length > 0)
                    {
                        return new Image(result);
                    }
                    else
                    {
                        return (null);
                    }
                }
                else
                {
                    GrabThumbNails();
                    _startupMessage = "Starting clipShow, please wait...";
                    return new Image("resx://ClipShowShell/ClipShowShell.Resources/clipShow_startup");
                }
            }
        }

        private string GetThumbnailFilePath()
        {
            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            bool foundNonTemp = false;
            string result = "";
            int ctr = 0;
            while (!foundNonTemp)
            {
                int nextThumb = r.Next(0, _thumbNails.Length - 1);
                if (!_thumbNails[nextThumb].EndsWith("_temp.jpg"))
                {
                    result = String.Format("file://{0}", _thumbNails[nextThumb]);
                    foundNonTemp = true;
                }
                ctr++;
                // Punt after 15 thumbs
                if (ctr > 15)
                {
                    result = "";
                    foundNonTemp = true;
                }
            }
            return (result);
        }

    }

    public class MediaFilter
    {
        private FilterTypeEnum _filterType = FilterTypeEnum.Year;
        private string _filterValue = "1800";
        private string _filterName = "1800";
        public MediaFilter()
        {
        }
        public MediaFilter(string Name, FilterTypeEnum Type, string Value)
        {
            _filterName = Name;
            _filterType = Type;
            _filterValue = Value;
        }
        public string Name
        {
            get { return (_filterName); }
            set { _filterName = value; }
        }
        public string Value
        {
            get { return (_filterValue); }
            set { _filterValue = value; }
        }
        public FilterTypeEnum Type
        {
            get { return (_filterType); }
            set { _filterType = value; }
        }
    }

    #region Enum definitions
    public enum FilterTypeEnum { All, Year, Month, Keyword, Similar, Navigation };
    public enum EditTextTypeEnum { Search, Playlist };
    public enum ClipLengths { Short = 45, Medium = 90, Long = 120, All = 0, Cancel=-1 };
    #endregion

    #region IComparer classes
    internal sealed class YearComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            MediaFilter firstInstance = x as MediaFilter;
            MediaFilter secondInstance = y as MediaFilter;
            int fI = Convert.ToInt32(firstInstance.Value);
            int sI = Convert.ToInt32(secondInstance.Value);
            return fI.CompareTo(sI);
        }
    }
    internal sealed class YearReverseComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            MediaFilter firstInstance = x as MediaFilter;
            MediaFilter secondInstance = y as MediaFilter;
            int fI = Convert.ToInt32(firstInstance.Value);
            int sI = Convert.ToInt32(secondInstance.Value);
            return sI.CompareTo(fI);
        }
    }
    #endregion

    public class CommandBarItem
    {
        private string _commandName = "";
        private ClipLengths _commandLength = ClipLengths.All;

        public CommandBarItem()
        {
        }

        public CommandBarItem(string commandName)
        {
            _commandName = commandName;
        }

        public CommandBarItem(string commandName, ClipLengths commandClipLength)
        {
            _commandName = commandName;
            _commandLength = commandClipLength;
        }

        public string CommandName
        {
            get { return (_commandName); }
            set { _commandName = value; }
        }

        public ClipLengths CommandLength
        {
            get { return (_commandLength); }
            set { _commandLength = value; }
        }
    }
    internal class MediaTimeLineMonth
    {
        private int _month = 1;
        private long _mediaCount = 1;
        public MediaTimeLineMonth(int Month)
        {
            _month = Month;
        }
        public string MonthLong
        {
            get { return (MonthConvertLong(_month)); }
        }
        public string MonthAbbr
        {
            get { return (MonthConvert(_month)); }
        }
        public void IncrementMedia()
        {
            _mediaCount++;
        }
        public long Count
        {
            get { return (_mediaCount); }
        }

        internal static string MonthConvertLong(int Month)
        {
            switch (Month)
            {
                case 1: return ("January");
                case 2: return ("February");
                case 3: return ("March");
                case 4: return ("April");
                case 5: return ("May");
                case 6: return ("June");
                case 7: return ("July");
                case 8: return ("August");
                case 9: return ("September");
                case 10: return ("October");
                case 11: return ("November");
                case 12: return ("December");
                default: return ("");
            }
        }

        internal static string MonthConvert(int Month)
        {
            switch (Month)
            {
                case 1: return ("Jan");
                case 2: return ("Feb");
                case 3: return ("Mar");
                case 4: return ("Apr");
                case 5: return ("May");
                case 6: return ("Jun");
                case 7: return ("Jul");
                case 8: return ("Aug");
                case 9: return ("Sep");
                case 10: return ("Oct");
                case 11: return ("Nov");
                case 12: return ("Dec");
                default: return ("");
            }
        }

    }
    internal class MediaTimeLineYear
    {
        private int _year = 1980;
        public Dictionary<int, MediaTimeLineMonth> AvailableMonths = new Dictionary<int, MediaTimeLineMonth>();
        public MediaTimeLineYear(int Year)
        {
            _year = Year;
        }
        public int Year
        {
            get { return (_year); }
        }
    }
    public class BrowserShell : ModelItem
    {
        private Dictionary<string, ArrayListDataSet> _mediaListCache;
        private Dictionary<string, TimeSpan> _mediaListCacheTS;
        private bool _dropdownPlaylist;
        private ClipShowContent _filteredMediaItems;
        private MediaList _mediaSelectionItems;
        private Command _mediaFilterRefreshed;
        private Command _mediaSelectionNew;
        private Command _popupMenuChangeState;
        private Command _mediaListRefreshed;
        private Command _menuContextChange;
        private Command _menuContextShow;
        private Command _refreshMediaItemSelected;
        private Command _buttonSelected;
        private Command _onscreenKeyboardShowing;
        private Command _transitionMediaList;
        private Command _menuDropdownShow;
        private Command _flipThumbs;
        private Command _showEditTextBox;
        private Command _showWaiting;
        private Command _mediaGatheringCompleted;
        private Int32 _mediaSelectionIndex = -1;
        private Choice _popupMenuItems;
        private bool _popupMenuOff = true;
        private Dictionary<int, MediaTimeLineYear> _mediaTimeLines;
        private Choice _filterBar;
        private Command _mediaFilterNew;
        private Command _mediaFilterApply;
        private ArrayList _appliedFilters = new ArrayList();
        private MediaFilter _currentFilter = new MediaFilter();
        private CommandBarItem _currentContextMenuItem = new CommandBarItem("none");
        private bool _playlistActive = false;
        private string _buttonSelectedDescription;
        private ArrayList _workingQueue;
        private EditTextTypeEnum _textType;
        private Settings _shellSettings;
        private const long MEDIALIST_CACHE_SETTING = 100;
        private int _curtainCounter = 0;
        private bool _mediaSearchFinished = false;
        TimeSpan _contentDuration = new TimeSpan();
        public BrowserShell()
        {
            Initialize();
            _mediaListCache = new Dictionary<string,ArrayListDataSet>();
            _mediaListCacheTS = new Dictionary<string, TimeSpan>();
            Notifier libStart = new Notifier();
            libStart.NotifierAlert += new NotifierEventHandler(MediaAvailable_NotifierAlert);
            libStart.NotifierException += new NotifierExceptionHandler(MediaAvailable_NotifierException);
            libStart.Start();
            
            _filteredMediaItems = new ClipShowContent();
        }

        #region Startup routines
        void MediaAvailable_NotifierException(object sender, NotifierExceptionArgs e)
        {
            if (e.NotifierExceptionText.Equals("Finish"))
            {
                _mediaSearchFinished = true;
                _mediaGatheringCompleted.Invoke();
            }
            else
            {
                AddInHost.Current.MediaCenterEnvironment.Dialog(e.NotifierExceptionText, "Media Search", DialogButtons.Ok, 30000, true);
                AddInHost.Current.ApplicationContext.CloseApplication();
            }
        }
        void MediaAvailable_NotifierAlert(object sender, NotifierEventArgs e)
        {
            Application.DeferredInvoke(InitializeListsFromSearch, e);
        }

        public void InitializeListsFromSearch(object Val)
        {
            NotifierEventArgs e = (NotifierEventArgs)Val;

            try
            {
                //if (_shellSettings.GroupAlikeClips)
                //{
                    // Add in the grouped settings
                    //foreach (ClipShowMetadata item in e.NotifierLibrary.MediaItems)
                    //{
                    //    ApplyGroupings(item);
                    //}

                    //_filteredMediaItems.MediaItems.Clear();
                    //foreach (ClipShowMetadata item in _groupedItems.Values)
                    //{
                    //    if (item.IsGroupItem)
                    //    {
                    //        item.Description = String.Format("{0}\n({1} similiar clips)",
                    //            item.GroupItemDescription, item.GroupItems.Count + 1);
                    //    }
                    //    _filteredMediaItems.MediaItems.Add(item);
                    //}
                //}
                //else
                //{
                    _filteredMediaItems.MediaItems.AddRange(e.NotifierLibrary.MediaItems);
                //}

                //ApplySort();

                //if (!e.NotifierLibrary.ContentSourceType.Equals(ContentSource.Local))
                //{
                //    if (!_mediaSelectionIndex.Equals(-1))
                //    {
                //        _lastKnownItem = (MediaListItem)this.MediaSelectionList[_mediaSelectionIndex];
                //    }
                //}
                

                // Clear our local cache for new media
                _mediaListCache.Clear();
                Dictionary<int, MediaTimeLineYear> mediaTimelines = new Dictionary<int, MediaTimeLineYear>();
                Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepTimeline),
                    new DeferredHandler(PostTimeline), mediaTimelines);

                Thumbs t = new Thumbs(e.NotifierLibrary);
                t.Start();

                StorageEngine.PersistMediaLibrary(_filteredMediaItems);

            }
            catch(SystemException se)
            {
                Debug.WriteLine(se.Message);
                AddInHost.Current.MediaCenterEnvironment.Dialog(se.Message, "Media Search", DialogButtons.Ok, 30000, true);
            }
        }

        public void Initialize()
        {
            _mediaFilterRefreshed = new Command();
            _mediaSelectionNew = new Command();
            _popupMenuChangeState = new Command();
            _mediaListRefreshed = new Command();
            _mediaFilterNew = new Command();
            _mediaFilterApply = new Command();
            _menuContextChange = new Command();
            _menuContextShow = new Command();
            _refreshMediaItemSelected = new Command();
            _buttonSelected = new Command();
            _onscreenKeyboardShowing = new Command();
            _transitionMediaList = new Command();
            _menuDropdownShow = new Command();
            _showEditTextBox = new Command();
            _mediaSelectionItems = new MediaList();
            _workingQueue = new ArrayList();
            _flipThumbs = new Command();
            _showWaiting = new Command();
            _mediaGatheringCompleted = new Command();

            // Grab settings
            _shellSettings = StorageEngine.GetSettings();
        }
        #endregion

        #region Internal routines
        internal static string MediaListLength(ArrayList source)
        {
            TimeSpan retVal = new TimeSpan();
            foreach (ClipShowMetadata current in source)
            {
                if (!current.Duration.Equals(-1))
                {
                    if (current.IsGroupItem)
                    {
                        retVal += TimeSpan.FromMilliseconds(current.Duration + current.GroupDuration);
                    }
                    else
                    {
                        retVal += TimeSpan.FromMilliseconds(current.Duration);
                    }

                }
            }
            return (TimeLengthInd(retVal));
        }
        internal static string TimeLengthInd(TimeSpan source)
        {
            string result = "";

            if (source.Hours.Equals(0))
            {
                if (source.Minutes.Equals(0))
                {
                    result = "";
                }
                else
                {
                    result = String.Format("({1}m)", source.Hours, source.Minutes);
                }
            }
            else
            {
                if (source.Minutes.Equals(0))
                {
                    result = String.Format("({0}h)", source.Hours);
                }
                else
                {
                    result = String.Format("({0}h{1}m)", source.Hours, source.Minutes);
                }
            }
            return (result);

        }
        internal static ClipShowContent BuildMediaList(string parentTopics, ClipShowContent source, ArrayList parentFilter)
        {
            ClipShowContent results = new ClipShowContent();
            string[] keywords = parentTopics.Split(';');

            if (keywords.Length > 0)
            {
                StringBuilder searchTerm = new StringBuilder();
                StringBuilder searchTermFilter = new StringBuilder();
                string finalTerm = "";
                string scopeTerm = "";
                foreach (MediaFilter mf in parentFilter)
                {
                    if (mf.Type.Equals(FilterTypeEnum.Keyword))
                    {
                        searchTermFilter.AppendFormat("{0} AND ", mf.Value);
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {

                        DateTime startDate = new DateTime(Convert.ToInt32(mf.Value), 1, 1);
                        DateTime endDate = new DateTime(Convert.ToInt32(mf.Value), 12, 31);
                        scopeTerm = String.Format("date:{0}..{1} ", startDate, endDate);
                    }
                }

                foreach (string topic in keywords)
                {
                    searchTerm.AppendFormat("{0} OR ", topic);
                }

                searchTerm.Remove(searchTerm.Length - 4, 4);

                if (searchTermFilter.Length > 1)
                {
                    searchTermFilter.Remove(searchTermFilter.Length - 5, 5);
                    finalTerm = String.Format("({0}) AND ({1})", searchTermFilter.ToString(), searchTerm.ToString());
                }
                else
                {
                    finalTerm = searchTerm.ToString();
                }

                if (scopeTerm.Length > 0)
                {
                    finalTerm = String.Format("{0} {1}", finalTerm, scopeTerm);
                }
                results = SearchEngine.QueryWindowsSearchAll(finalTerm);
            }
            return (results);
        }
        internal static ArrayListDataSet BuildMediaList(ClipShowContent source, ArrayListDataSet temp)
        {
            temp.CopyFrom(source.MediaItems);
            return (temp);
        }
        internal static ArrayListDataSet BuildMediaList(DateTime startDate, DateTime endDate, ClipShowContent source, ArrayListDataSet temp)
        {
            foreach (ClipShowMetadata med in source.MediaItems)
            {
                if (DateTime.Compare(med.CreationDateTime, startDate) >= 0)
                {
                    if (DateTime.Compare(med.CreationDateTime, endDate) <= 0)
                    {
                        temp.Add(med);
                    }
                }
            }
            return (temp);
        }
        internal static TimeSpan SetSkip(long sourceDuration, int clipLength)
        {
            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            try
            {
                TimeSpan sourceTS = new TimeSpan(sourceDuration * 10000);
                Int32 skipMinute = 0;
                Int32 skipSecond = 0;
                Int32 skipHour = 0;

                if (sourceTS.Hours > 1)
                {
                    skipHour = r.Next(0, sourceTS.Hours - 1);
                    skipMinute = r.Next(0, 59);
                    skipSecond = r.Next(0, 59);
                }
                else if (sourceTS.Minutes > 1)
                {
                    skipMinute = r.Next(0, sourceTS.Minutes - 1);
                    skipSecond = r.Next(0, 59);
                }
                else
                {
                    skipSecond = r.Next(0, sourceTS.Seconds);
                }

                TimeSpan ts = new TimeSpan(skipHour, skipMinute, skipSecond);
                return (ts);
            }
            catch
            {
                return (new TimeSpan(0));
            }
        }
        internal static void ShuffleMediaList(MediaList arrayList, Random random)
        {
            if (arrayList == null) { return; }
            int count = arrayList.Count;
            for (int i = 0; i < count; i++)
            {
                MediaListItem tmp = (MediaListItem)arrayList[i];
                int nextIndex = random.Next(count);

                arrayList[i] = arrayList[nextIndex];
                arrayList[nextIndex] = tmp;
            }
        }
        internal static ClipShowContent BuildMediaList(ClipShowContent source, ArrayList parentFilter)
        {
            StringBuilder searchTerm = new StringBuilder();
            string scopeTerm = "";
            if (parentFilter.Count > 0)
            {
                // Now iterate through and apply filters
                foreach (MediaFilter mf in parentFilter)
                {
                    if (mf.Type.Equals(FilterTypeEnum.Keyword))
                    {
                        searchTerm.AppendFormat("{0} AND ", mf.Value);
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {
                        DateTime startDate = new DateTime(Convert.ToInt32(mf.Value), 1, 1);
                        DateTime endDate = new DateTime(Convert.ToInt32(mf.Value), 12, 31);
                        scopeTerm = String.Format("date:{0}..{1} ", startDate, endDate);
                    }
                }
            }
            searchTerm.Remove(searchTerm.Length - 5, 5);

            if (scopeTerm.Length > 0)
            {
                searchTerm.AppendFormat(" {0}", scopeTerm);
            }
            ClipShowContent results = SearchEngine.QueryWindowsSearchAll(searchTerm.ToString());
            return (results);
        }
        internal protected void PrepTimeline(object args)
        {
            Dictionary<int, MediaTimeLineYear> myTimelines = (Dictionary<int, MediaTimeLineYear>)args;
            foreach (ClipShowMetadata item in _filteredMediaItems.MediaItems)
            {
                if (!myTimelines.ContainsKey(item.CreationDateTime.Year))
                {
                    MediaTimeLineYear tly = new MediaTimeLineYear(item.CreationDateTime.Year);
                    MediaTimeLineMonth tmd = new MediaTimeLineMonth(item.CreationDateTime.Month);
                    tly.AvailableMonths.Add(item.CreationDateTime.Month, tmd);
                    myTimelines.Add(item.CreationDateTime.Year, tly);
                }
                else
                {
                    if (myTimelines[item.CreationDateTime.Year].AvailableMonths.ContainsKey(item.CreationDateTime.Month))
                    {
                        myTimelines[item.CreationDateTime.Year].AvailableMonths[item.CreationDateTime.Month].IncrementMedia();
                    }
                    else
                    {
                        MediaTimeLineMonth tmd = new MediaTimeLineMonth(item.CreationDateTime.Month);
                        myTimelines[item.CreationDateTime.Year].AvailableMonths.Add(item.CreationDateTime.Month, tmd);
                    }
                }
            }
        }
        internal protected void PostTimeline(object args)
        {
            _mediaTimeLines = (Dictionary<int, MediaTimeLineYear>)args;

            if (_mediaTimeLines.Count > 0)
            {
                if (this.CurrentFilter.Type.Equals(FilterTypeEnum.Year))
                {
                    PopulateYearTimeline(Convert.ToInt32(this.CurrentFilter.Value));
                }
                else
                {
                    // Do nothing for now as we are in a month filter and we will not refresh the current year list
                }
            }

        }
        internal void PopulateYearTimeline(int prevYear)
        {
            _filterBar = new Choice();
            int focusIndex = 0;

            ArrayListDataSet temp = new ArrayListDataSet();
            foreach (int Year in _mediaTimeLines.Keys)
            {
                MediaFilter mf = new MediaFilter(Year.ToString(), FilterTypeEnum.Year, Year.ToString());
                temp.Add(mf);
            }

            SortFilterList(temp, _shellSettings.MediaSortOption);

            if (prevYear == 1800)
            {
                foreach (MediaFilter mf in _appliedFilters)
                {
                    if ((mf.Type.Equals(FilterTypeEnum.Keyword)) || (mf.Type.Equals(FilterTypeEnum.Similar)))
                    {
                        // Only show the All filter if more than one year of media is returned
                        if (_mediaTimeLines.Count > 1)
                        {
                            temp.Insert(0, new MediaFilter("All", FilterTypeEnum.All, "All"));
                            break;
                        }
                    }
                }

            }

            // Now iterate and capture new default index if we need it for UI focus
            if (!prevYear.Equals(1800))
            {
                for (int i = 1; i < temp.Count; i++)
                {
                    MediaFilter mf = (MediaFilter)temp[i];
                    if (Convert.ToInt32(mf.Value).Equals(prevYear))
                    {
                        focusIndex = i;
                        break;
                    }
                }
            }
            _filterBar.Options = temp;
            if (!prevYear.Equals(1800))
            {
                _filterBar.DefaultIndex = focusIndex;
            }
            //else
            //{
            //    _filterBar.DefaultIndex = 1;    // Set it to most recent year found
            //}

            _mediaFilterRefreshed.Invoke();
        }
        internal static void SortList(ArrayListDataSet source, ClipShow2.Storage.SortOptions targetOption)
        {
            if(targetOption.Equals(SortOptions.ByDateReverse))
            {
                MediaByDateReverseComparer mrc = new MediaByDateReverseComparer();
                source.Sort(mrc);
            }
            if (targetOption.Equals(SortOptions.ByDate))
            {
                MediaByDateComparer mrc = new MediaByDateComparer();
                source.Sort(mrc);
            }
            if (targetOption.Equals(SortOptions.ByName))
            {
                MediaByNameComparer mrc = new MediaByNameComparer();
                source.Sort(mrc);
            }
        }
        internal static void SortFilterList(ArrayListDataSet source, ClipShow2.Storage.SortOptions targetOption)
        {
            if (targetOption.Equals(SortOptions.ByDateReverse))
            {
                YearReverseComparer yrc = new YearReverseComparer();
                source.Sort(yrc);
            }
            if (targetOption.Equals(SortOptions.ByDate))
            {
                YearComparer yc = new YearComparer();
                source.Sort(yc);
            }
            if (targetOption.Equals(SortOptions.ByName))
            {
                YearReverseComparer yrc = new YearReverseComparer();
                source.Sort(yrc);
            }
        }
        internal protected void PrepFilter(object args)
        {
            ArrayListDataSet temp = (ArrayListDataSet)args;
            MediaFilter FilterValue = (MediaFilter)temp[0];
            temp.Clear();

            if (FilterValue.Type.Equals(FilterTypeEnum.Similar))
            {
                temp.CopyFrom(BuildMediaList(FilterValue.Value, _filteredMediaItems, _appliedFilters).MediaItems);
                args = temp;
            }
            if (FilterValue.Type.Equals(FilterTypeEnum.Keyword))
            {
                temp.CopyFrom(BuildMediaList(_filteredMediaItems, _appliedFilters).MediaItems);
                args = temp;
            }
            if (FilterValue.Type.Equals(FilterTypeEnum.All))
            {
                args = BuildMediaList(_filteredMediaItems, temp);
            }
            if (FilterValue.Type.Equals(FilterTypeEnum.Year))
            {
                DateTime startDate = new DateTime(Convert.ToInt32(FilterValue.Value), 1, 1);
                DateTime endDate = new DateTime(Convert.ToInt32(FilterValue.Value), 12, 31);
                args = BrowserShell.BuildMediaList(startDate, endDate, _filteredMediaItems,temp);
            }
            if (FilterValue.Type.Equals(FilterTypeEnum.Month))
            {
                // Pull out the year from applied filters
                int lastFilterIndex = _appliedFilters.Count - 1;
                MediaFilter lastFilter = new MediaFilter(); // (MediaFilter)_appliedFilters[lastFilterIndex];
                // Find the Year filter
                foreach (MediaFilter fil in _appliedFilters)
                {
                    if (fil.Type.Equals(FilterTypeEnum.Year))
                    {
                        lastFilter = fil;
                        break;
                    }
                }
                DateTime startDate = new DateTime(Convert.ToInt32(lastFilter.Value), Convert.ToInt32(FilterValue.Value), 1);
                DateTime endDate = startDate.AddMonths(1).AddDays(-1);
                args = BrowserShell.BuildMediaList(startDate, endDate, _filteredMediaItems,temp);
            }
        }
        internal protected void PostFilter(object args)
        {
            _contentDuration = new TimeSpan(0);
            if ((_currentFilter.Type.Equals(FilterTypeEnum.Keyword)) || (_currentFilter.Type.Equals(FilterTypeEnum.Similar)))
            {
                ArrayListDataSet results = (ArrayListDataSet)args;
                ArrayListDataSet target = new ArrayListDataSet();
                if (results.Count > 0)
                {
                    // First apply sort based upon sort option selected
                    SortList(results, _shellSettings.MediaSortOption);

                    _filteredMediaItems.MediaItems.Clear();
                    _filteredMediaItems.MediaItems.AddRange(results);
                    foreach (ClipShowMetadata med in results)
                    {
                        MediaListItem mli = new MediaListItem(med);
                        target.Add(mli);
                        if (!mli.SourceItem.Duration.Equals(-1))
                        {
                            if (mli.SourceItem.IsGroupItem)
                            {
                                _contentDuration += TimeSpan.FromMilliseconds(mli.SourceItem.Duration + mli.SourceItem.GroupDuration);
                            }
                            else
                            {
                                _contentDuration += TimeSpan.FromMilliseconds(mli.SourceItem.Duration);
                            }

                        }
                    }
                    this.MediaSelectionList.Clear();
                    this.MediaSelectionList.Source = target;

                    // Build out new timelines for media
                    Dictionary<int, MediaTimeLineYear> mediaTimelines = new Dictionary<int, MediaTimeLineYear>();
                    Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepTimeline),
                        new DeferredHandler(PostTimeline), mediaTimelines);

                    _mediaListRefreshed.Invoke();
                    _mediaFilterApply.Invoke();
                    _mediaFilterNew.Invoke();
                }
                else
                {
                    // Remove 'bad' keyword filter
                    _appliedFilters.Remove(_currentFilter);
                    try
                    {
                        AddInHost.Current.MediaCenterEnvironment.Dialog(
                            String.Format("No media items were found matching '{0}'", _currentFilter.Value), "clipShow Search", DialogButtons.Ok, 30000, true);
                    }
                    catch { }
                }
            }
            else
            {
                ArrayListDataSet temp = (ArrayListDataSet)args;
                SortList(temp, _shellSettings.MediaSortOption);
                
                ArrayListDataSet target = new ArrayListDataSet();
                
                foreach (ClipShowMetadata med in temp)
                {
                    MediaListItem mli = new MediaListItem(med);
                    if (!mli.SourceItem.Duration.Equals(-1))
                    {
                        if (mli.SourceItem.IsGroupItem)
                        {
                            _contentDuration += TimeSpan.FromMilliseconds(mli.SourceItem.Duration + mli.SourceItem.GroupDuration);
                        }
                        else
                        {
                            _contentDuration += TimeSpan.FromMilliseconds(mli.SourceItem.Duration);
                        }

                    }
                    target.Add(mli);
                }
                this.MediaSelectionList.Clear();
                this.MediaSelectionList.Source = target;
                _mediaListRefreshed.Invoke();

                // Only use cache if we are over set limit of items
                if (target.Count > MEDIALIST_CACHE_SETTING)
                {
                    // Check if cache has been populated
                    string key = "";
                    if (_currentFilter.Type.Equals(FilterTypeEnum.Month))
                    {
                        MediaFilter year = (MediaFilter)_appliedFilters[0];
                        key = String.Format("{0}:{1}", year.Value, _currentFilter.Value);
                    }

                    if (_currentFilter.Type.Equals(FilterTypeEnum.Year))
                    {
                        key = _currentFilter.Value;
                    }

                    if (key.Length > 0)
                    {
                        if (!_mediaListCache.ContainsKey(key))
                        {
                            _mediaListCache.Add(key, target);
                            _mediaListCacheTS.Add(key, _contentDuration);
                        }

                    }
                }
            }
        }
        internal static void SavePlaylist(string playListName, ArrayList source)
        {
            try
            {
                ClipShow2.Storage.StorageEngine.CreateASX(source, playListName);
            }
            catch
            {
                AddInHost.Current.MediaCenterEnvironment.Dialog("Exception when saving the playlist", "Playlist", DialogButtons.Ok, 30000, true);
            }
        }
        #endregion

        #region Methods
        public void SaveSettings()
        {
            try
            {
                StorageEngine.PersistSettings(_shellSettings);
                ResetFilter();
            }
            catch (SystemException se)
            {
                AddInHost.Current.MediaCenterEnvironment.Dialog(se.Message, "Save Settings", DialogButtons.Ok, 30000, true);
            }
        }
        public void ProcessDropdownMenuItem(CommandBarItem current)
        {
            if (!current.CommandLength.Equals(ClipLengths.Cancel))
            {
                int clipLengthInSeconds = (Int32)current.CommandLength;
                if (_dropdownPlaylist)
                {

                    if (clipLengthInSeconds == 0)
                    {
                        try
                        {
                            DialogResult dr = AddInHost.Current.MediaCenterEnvironment.Dialog("Save this playlist?",
                                "Playlist options", DialogButtons.Yes | DialogButtons.No | DialogButtons.Cancel, 30000, true);

                            if (dr.Equals(DialogResult.Cancel))
                            {
                                _menuContextChange.Invoke();
                                return;
                            }

                            if (dr.Equals(DialogResult.Yes))
                            {
                                // Invoke Save textbox for playlist name
                                _showEditTextBox.Invoke();
                            }

                            if (dr.Equals(DialogResult.No))
                            {
                                _menuContextChange.Invoke();
                                WatchPlaylist(clipLengthInSeconds);
                            }

                        }
                        catch { }
                    }
                    else
                    {
                        WatchPlaylist(clipLengthInSeconds);
                        _menuContextChange.Invoke();
                    }
                }
                else
                {
                    WatchFilter(clipLengthInSeconds);
                    _menuContextChange.Invoke();
                }
            }
            else
            {
                _menuContextChange.Invoke();
            }
            
        }
        public void ProcessContextMenuItem(CommandBarItem current)
        {
            _currentContextMenuItem = current;
            MediaListItem selectedItem = (MediaListItem)this.MediaSelectionList[_mediaSelectionIndex];
            if (!current.CommandName.Equals("Cancel"))
            {
                #region Remove from playlist
                if (current.CommandName.Equals("Remove from playlist"))
                {
                    ManagePlaylist(selectedItem.SourceItem, true);
                }
                #endregion
                #region Add to playlist
                if (current.CommandName.Equals("Add to my playlist"))
                {
                    ManagePlaylist(selectedItem.SourceItem, false);
                }
                #endregion
                #region Play selected video
                if (current.CommandName.Equals("Watch videos") || (current.CommandName.Equals("Watch video")))
                {
                    // Play selected video
                    PlaySingleMediaItem(selectedItem.SourceItem,0);
                    _refreshMediaItemSelected.Invoke();
                }
                #endregion
                #region Add to now playing
                if (current.CommandName.Equals("Add to Now Playing"))
                {
                    MediaCollection mc = new MediaCollection();
                    AddInHost.Current.MediaCenterEnvironment.MediaExperience.GetMediaCollection(mc);
                    if (mc.IsActive)
                    {

                        if (selectedItem.SourceItem.IsGroupItem)
                        {
                            foreach (ClipShowMetadata groupItem in selectedItem.SourceItem.GroupItems)
                            {
                                mc.Add(BuildMCI(groupItem, 0));
                            }
                        }
                        else
                        {
                            MediaCollectionItem mci = new MediaCollectionItem();
                            mci.Media = selectedItem.SourceItem.Url;
                            mci.PlaybackFlags = MediaItemPlaybackCapabilities.All;
                            mc.Add(mci);
                        }
                    }
                    else
                    {
                        PlaySingleMediaItem(selectedItem.SourceItem,0);
                    }
                    _refreshMediaItemSelected.Invoke();
                }
                #endregion
                #region Find similar
                if (current.CommandName.Equals("Find like media"))
                {
                    // Check for existing 'similar' filter and remove it
                    foreach (MediaFilter mfCheck in _appliedFilters)
                    {
                        if (mfCheck.Type.Equals(FilterTypeEnum.Similar))
                        {
                            _appliedFilters.Remove(mfCheck);
                            break;
                        }
                    }

                    Topics top = new Topics();
                    string medParentTopics = top.BuildSingleTopic(selectedItem.SourceItem);
                    MediaFilter mf = new MediaFilter(selectedItem.SourceItem.Title, FilterTypeEnum.Similar, medParentTopics);
                    _appliedFilters.Add(mf);
                    ChangeViewByFilter(mf);
                }
                #endregion
                #region Break apart grouping
                if (current.CommandName.Equals("Break apart grouping"))
                {
                    RemoveGrouping(selectedItem.SourceItem);
                }
                #endregion
                #region Group item
                if (current.CommandName.Equals("Group by date"))
                {
                    CreateGrouping(selectedItem.SourceItem);
                }
                #endregion
            }
            else
            {
                _refreshMediaItemSelected.Invoke();
            }
            
            _menuContextChange.Invoke();
        }
        public void CreateGrouping(ClipShowMetadata source)
        {
            ArrayList removeItems = new ArrayList();
            string groupKey = source.CreationDateTime.ToShortDateString();
            ClipShowMetadata target = new ClipShowMetadata();

            target.Description = source.Description;
            target.Title = source.Title;
            target.Duration = 0;
            target.ThumbnailUrl = source.ThumbnailUrl;
            target.CreationDateTime = source.CreationDateTime;
            target.Url = source.Url;
            target.IsGroupItem = true;
            target.IsPlaylistItem = source.IsPlaylistItem;

            foreach (ClipShowMetadata item in _filteredMediaItems.MediaItems)
            {
                if (groupKey.Equals(item.CreationDateTime.ToShortDateString()))
                {
                    removeItems.Add(item);
                    target.GroupItems.Add(item);
                    if (!item.Duration.Equals(-1))
                    {
                        target.GroupDuration += item.Duration;
                    }
                    if (item.IsGroupItem)
                    {
                        target.GroupItems.AddRange(item.GroupItems);
                        removeItems.AddRange(item.GroupItems);
                    }

                }
            }

            target.Description = String.Format("{0}\n({1} clips grouped by date)",
                target.Description, target.GroupItems.Count);

            // Note that the item itself will appear in remove items
            if (removeItems.Count > 1)
            {
                foreach (ClipShowMetadata item in removeItems)
                {
                    _filteredMediaItems.MediaItems.Remove(item);
                    
                    foreach (MediaListItem mli in this.MediaSelectionList)
                    {
                        if (mli.SourceItem.Url.Equals(item.Url))
                        {
                            if (mli.SourceItem.Url.Equals(target.Url))
                            {
                                mli.SourceItem = target;
                            }
                            else
                            {
                                this.MediaSelectionList.Remove(mli);
                            }
                            break;
                        }
                    }
                }
                _filteredMediaItems.MediaItems.Add(target);

                int ctr = 0;
                foreach (MediaListItem mli in this.MediaSelectionList)
                {
                    if (mli.SourceItem.Url.Equals(target.Url))
                    {
                        _mediaSelectionIndex = ctr;
                        break;
                    }
                    ctr++;
                }
            }
            else
            {
                target.IsGroupItem = false;
            }

            _refreshMediaItemSelected.Invoke();
        }
        public void ManagePlaylist(ClipShowMetadata source, bool IsPlaylistItem)
        {
            if (!IsPlaylistItem)
            {
                source.IsPlaylistItem = true;

                if (source.IsGroupItem)
                {
                    foreach (ClipShowMetadata child in source.GroupItems)
                    {
                        child.IsPlaylistItem = true;
                        _workingQueue.Add(child);
                    }
                }
                else
                {
                    _workingQueue.Add(source);
                }
            }
            else
            {
                source.IsPlaylistItem = false;

                if (source.IsGroupItem)
                {
                    foreach (ClipShowMetadata child in source.GroupItems)
                    {
                        child.IsPlaylistItem = false;
                        _workingQueue.Remove(child);
                    }
                }
                else
                {
                    _workingQueue.Remove(source);
                }

            }

            _refreshMediaItemSelected.Invoke();
            _playlistActive = true;
        }
        public void RemoveGrouping(ClipShowMetadata source)
        {
            this.MediaSelectionList.RemoveAt(_mediaSelectionIndex);

            _filteredMediaItems.MediaItems.Remove(source);
            foreach (ClipShowMetadata item in source.GroupItems)
            {
                item.IsGroupItem = false;
                this.MediaSelectionList.Insert(_mediaSelectionIndex, new MediaListItem(item));
                _filteredMediaItems.MediaItems.Add(item);
            }

            int ctr = 0;
            ClipShowMetadata focusMediaItem = (ClipShowMetadata)source.GroupItems[0];
            foreach (MediaListItem mli in this.MediaSelectionList)
            {
                if (mli.SourceItem.Url.Equals(focusMediaItem.Url))
                {
                    _mediaSelectionIndex = ctr;
                    break;
                }
                ctr++;
            }
            source.GroupItems.Clear();
            _refreshMediaItemSelected.Invoke();
        }
        public void ApplyFilter(MediaFilter Filter)
        {
            if (!Filter.Name.Equals("All"))
            {
                // Now branch on filter type
                if (Filter.Type.Equals(FilterTypeEnum.Year))
                {

                    bool yearAdded = false;
                    foreach (MediaFilter mf in _appliedFilters)
                    {
                        if(mf.Type.Equals(FilterTypeEnum.Year))
                        {
                            yearAdded = true;
                            break;
                        }
                    }
                    if(!yearAdded)
                    {
                        // Add it to applied filters
                        _appliedFilters.Add(Filter);
                    }
                    
                    // Build out months
                    _filterBar.Options.Clear();
                    ArrayListDataSet temp = new ArrayListDataSet();
                    foreach (int monthKey in _mediaTimeLines[Convert.ToInt32(Filter.Value)].AvailableMonths.Keys)
                    {
                        MediaTimeLineMonth month = _mediaTimeLines[Convert.ToInt32(Filter.Value)].AvailableMonths[monthKey];
                        MediaFilter mf = new MediaFilter(month.MonthAbbr, FilterTypeEnum.Month, monthKey.ToString());
                        temp.Add(mf);
                    }

                    SortFilterList(temp, _shellSettings.MediaSortOption);
                    temp.Insert(0, new MediaFilter("back", FilterTypeEnum.Navigation, "back"));
                    _filterBar.Options = temp;
                    _filterBar.DefaultIndex = 1;

                    // Notify the UI to refresh
                    _mediaFilterApply.Invoke();
                    _mediaFilterRefreshed.Invoke();
                }
                if (Filter.Type.Equals(FilterTypeEnum.Navigation))
                {
                    // Pull out the year from applied filters
                    int lastFilterIndex = _appliedFilters.Count - 1;
                    MediaFilter lastFilter = (MediaFilter)_appliedFilters[lastFilterIndex];
                    if (lastFilter.Type.Equals(FilterTypeEnum.Year))
                    {
                        _appliedFilters.RemoveAt(lastFilterIndex);
                        PopulateYearTimeline(Convert.ToInt32(lastFilter.Value));
                        _mediaFilterApply.Invoke();
                    }
                    else
                    {
                        ChangeViewByFilter(lastFilter);
                        //_appliedFilters.RemoveAt(lastFilterIndex);
                    }
                }
            }
        }
        public void ProcessEditText(string TextValue)
        {
            if (!TextValue.Equals(""))
            {
                if (this.EditTextType.Equals(EditTextTypeEnum.Search))
                {
                    ChangeViewByKeyword(TextValue);
                }
                if (this.EditTextType.Equals(EditTextTypeEnum.Playlist))
                {
                    SavePlaylist(TextValue, _workingQueue);
                    WatchPlaylist(0);
                    _menuContextChange.Invoke();
                    AddInHost.Current.MediaCenterEnvironment.Dialog("Saved playlist can be found in Public Videos in the 'clipShow playlists' folder",
                        "Saved playlist", DialogButtons.Ok, 15000, false);
                }
            }
        }
        public void ChangeViewByKeyword(string Keyword)
        {
            // First clear out list cache
            _mediaListCache.Clear();

            MediaFilter mf = new MediaFilter(Keyword, FilterTypeEnum.Keyword, Keyword);
            _appliedFilters.Add(mf);
            ChangeViewByFilter(mf);
        }
        public void ChangeViewByFilter(MediaFilter FilterValue)
        {
            if (!_currentFilter.Equals(FilterValue))
            {
                #region Check media list cache
                string key = "";

                if (FilterValue.Type.Equals(FilterTypeEnum.Month))
                {
                    MediaFilter year = (MediaFilter)_appliedFilters[0];
                    key = String.Format("{0}:{1}", year.Value, FilterValue.Value);
                }

                if (FilterValue.Type.Equals(FilterTypeEnum.Year))
                {
                    key = FilterValue.Value;
                }

                if (key.Length > 0)
                {
                    if (_mediaListCache.ContainsKey(key))
                    {
                        _transitionMediaList.Invoke();
                        this.MediaSelectionList.Clear();
                        this.MediaSelectionList.Source = _mediaListCache[key];
                        _contentDuration = _mediaListCacheTS[key];
                        _mediaListRefreshed.Invoke();
                        _currentFilter = FilterValue;
                    }
                    else
                    {
                        // Alert UI that we are transitioning media list
                        _transitionMediaList.Invoke();

                        ArrayListDataSet temp = new ArrayListDataSet();
                        temp.Add(FilterValue);
                        Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepFilter),
                            new DeferredHandler(PostFilter), temp);
                        _currentFilter = FilterValue;

                    }
                }
                #endregion
                else
                {
                    // Alert UI that we are transitioning media list
                    _transitionMediaList.Invoke();

                    ArrayListDataSet temp = new ArrayListDataSet();
                    temp.Add(FilterValue);
                    Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepFilter),
                        new DeferredHandler(PostFilter), temp);
                    _currentFilter = FilterValue;
                }
            }
            _mediaFilterNew.Invoke();
        }
        public void ResetFilter()
        {
            _mediaSearchFinished = false;
            _mediaGatheringCompleted.Invoke();
            _showWaiting.Invoke();
            _playlistActive = false;
            _workingQueue.Clear();
            this.MediaSelectionList.Clear();
            this.FilterList.Options.Clear();
            _currentFilter = new MediaFilter();
            _mediaListCache.Clear();

            // Clear the applied filter collection
            _appliedFilters.Clear();
            _refreshMediaItemSelected.Invoke();

            Notifier libStart = new Notifier();
            libStart.NotifierAlert += new NotifierEventHandler(MediaAvailable_NotifierAlert);
            libStart.NotifierException += new NotifierExceptionHandler(MediaAvailable_NotifierException);
            libStart.Start();
            _filteredMediaItems = new ClipShowContent();
        }
        public void ShowOnScreenKeyboard(EditableText editText)
        {
            try
            {
                AddInHost.Current.MediaCenterEnvironment.ShowOnscreenKeyboard(editText, false, 30);
                _onscreenKeyboardShowing.Invoke();
            }
            catch
            {
                Console.Write("Showing onscreen keyboard");
            }
        }
        public MediaCollection PlaySingleMediaItem(ClipShowMetadata source, int clipLength)
        {
            MediaCollection playBack = new MediaCollection();
            playBack.ContinueOnError = true;

            try
            {
                if (source.IsGroupItem)
                {
                    foreach (ClipShowMetadata groupItem in source.GroupItems)
                    {
                        playBack.Add(BuildMCI(groupItem, clipLength));
                    }
                }
                else
                {
                    //MediaCollectionItem mci = new MediaCollectionItem();
                    //mci.Media = source.Url;
                    //mci.PlaybackFlags = MediaItemPlaybackCapabilities.All;
                    playBack.Add(BuildMCI(source, clipLength));
                }

                AddInHost.Current.MediaCenterEnvironment.PlayMedia(Microsoft.MediaCenter.MediaType.MediaCollection,
                    playBack, false);
                AddInHost.Current.MediaCenterEnvironment.MediaExperience.GoToFullScreen();

            }
            catch
            {
                Debug.Write(String.Format("Playing '{0}'", source.Url));
            }

            return (playBack);

        }
        /// <summary>
        /// Deprecated on 4/11/2010 with new queue then play capability
        /// </summary>
        /// <param name="source"></param>
        public void PlayMediaCollection(MediaCollection source)
        {
            try
            {
                AddInHost.Current.MediaCenterEnvironment.PlayMedia(Microsoft.MediaCenter.MediaType.MediaCollection,
                    source, false);
                AddInHost.Current.MediaCenterEnvironment.MediaExperience.GoToFullScreen();
            }
            catch
            {
                Console.Write("Playing media collection");
            }
        }
        private bool IsMediaCollectionPlaying()
        {
            bool result = false;
            MediaCollection mc = new MediaCollection();
            try
            {
                AddInHost.Current.MediaCenterEnvironment.MediaExperience.GetMediaCollection(mc);
                result = mc.IsActive;
            }
            catch
            {
                
            }
            return (result);
        }
        public void CheckMediaItemContext(MediaListItem source)
        {
            CommandBarItem playListOption = new CommandBarItem();
            if (source.SourceItem.IsPlaylistItem)
            {
                playListOption.CommandName = "Remove from playlist";
            }
            else
            {
                playListOption.CommandName = "Add to my playlist";
            }

            _popupMenuItems = new Choice();
            ArrayListDataSet temp = new ArrayListDataSet();
            if (IsMediaCollectionPlaying())
            {
                temp.Add(new CommandBarItem("Add to Now Playing"));
            }
            else
            {
                if (source.SourceItem.IsGroupItem)
                {
                    temp.Add(new CommandBarItem("Watch videos"));
                }
                else
                {
                    temp.Add(new CommandBarItem("Watch video"));
                }
            }
            temp.Add(playListOption);

            temp.Add(new CommandBarItem("Find like media"));

            if (source.SourceItem.IsGroupItem)
            {
                temp.Add(new CommandBarItem("Break apart grouping"));
            }
            else
            {
                temp.Add(new CommandBarItem("Group by date"));
            }
            
            temp.Add(new CommandBarItem("Cancel"));

            _popupMenuItems.Options = temp;

        }
        public void PlayMenuOptions(bool isPlayList)
        {
            _dropdownPlaylist = isPlayList;
            ArrayListDataSet temp = new ArrayListDataSet();
            temp.Add(new CommandBarItem("In its entirety", ClipLengths.All));
            temp.Add(new CommandBarItem("45 second clips", ClipLengths.Short));
            temp.Add(new CommandBarItem("90 second clips", ClipLengths.Medium));
            temp.Add(new CommandBarItem("2 minute clips", ClipLengths.Long));
            temp.Add(new CommandBarItem("Cancel", ClipLengths.Cancel));

            _popupMenuItems = new Choice();
            _popupMenuItems.Options = temp;
            _menuDropdownShow.Invoke();
        }
        public void InMenuButton(string description, string buttonName)
        {
            string result = "";
            if (buttonName.Equals("play"))
            {
                result = String.Format("view these {0} in a playlist", this.MediaFilterCurrentDetail);
            }
            else if (buttonName.Equals("watch"))
            {
                result = String.Format("view {0} items in a playlist", this._workingQueue.Count);
            }
            else
            {
                result = description;
            }
            _buttonSelectedDescription = result;
            _buttonSelected.Invoke();
        }
        private void WatchPlaylist(int clipLength)
        {
            MediaCollection playBack = new MediaCollection();
            playBack.ContinueOnError = true;

            Boolean firstIn = true;

            foreach (ClipShowMetadata med in _workingQueue)
            {
                if (med.IsGroupItem)
                {
                    foreach (ClipShowMetadata groupItem in med.GroupItems)
                    {
                        if (firstIn.Equals(true))
                        {
                            playBack = PlaySingleMediaItem(groupItem, clipLength);
                            firstIn = false;
                        }
                        else
                        {
                            playBack.Add(BuildMCI(groupItem, clipLength));
                        }
                    }
                }
                else
                {
                    if (firstIn.Equals(true))
                    {
                        playBack = PlaySingleMediaItem(med, clipLength);
                        firstIn = false;
                    }
                    else
                    {
                        playBack.Add(BuildMCI(med, clipLength));
                    }
                }
            }
            //CS - 4/11/2010 - No longer needed as we now play the first item and the queue
            //PlayMediaCollection(playBack);
        }
        private MediaCollectionItem BuildMCI(ClipShowMetadata source, int clipLength)
        {
            bool playClips = (clipLength != 0);
            MediaCollectionItem mci = new MediaCollectionItem();
            mci.Media = source.Url;
            mci.PlaybackFlags = MediaItemPlaybackCapabilities.All;
            if (playClips)
            {
                mci.Start = SetSkip(source.Duration, clipLength);
                mci.End = mci.Start;
                mci.End = mci.End.Add(TimeSpan.FromSeconds(clipLength));
            }
            return (mci);
        }
        public void InvokeFlipThumbs()
        {
            _flipThumbs.Invoke();
        }
        public void WatchFilter(int clipLength)
        {
            try
            {
                DialogResult dr = AddInHost.Current.MediaCenterEnvironment.Dialog("Shuffle playback of selected media?",
                    "Playback options", DialogButtons.Yes | DialogButtons.No | DialogButtons.Cancel, 30000, true);

                if (dr.Equals(DialogResult.Cancel))
                {
                    return;
                }

                if (dr.Equals(DialogResult.Yes))
                {
                    Random r = new Random(unchecked((Int32)DateTime.Now.Ticks));
                    ShuffleMediaList(this.MediaSelectionList, r);
                }
            }
            catch { }

            MediaCollection playBack = new MediaCollection();
            playBack.ContinueOnError = true;
            Boolean firstIn = true;

            foreach (MediaListItem mli in this.MediaSelectionList)
            {
                if (mli.SourceItem.IsGroupItem)
                {
                    foreach (ClipShowMetadata groupItem in mli.SourceItem.GroupItems)
                    {
                        if (firstIn.Equals(true))
                        {
                            playBack = PlaySingleMediaItem(groupItem, clipLength);
                            firstIn = false;
                        }
                        else
                        {
                            playBack.Add(BuildMCI(groupItem, clipLength));
                        }

                    }
                }
                else
                {
                    if (firstIn.Equals(true))
                    {
                        playBack = PlaySingleMediaItem(mli.SourceItem, clipLength);
                        firstIn = false;
                    }
                    else
                    {
                        playBack.Add(BuildMCI(mli.SourceItem, clipLength));
                    }
                }
            }

            //PlayMediaCollection(playBack);
        }

        #endregion

        #region MCML Properties
        public int CurtainCounter
        {
            get
            {
                _curtainCounter += 1;
                return (_curtainCounter);
            }
            set { _curtainCounter = value; }
        }

        public bool IsNowPlaying
        {
            get
            {
                try
                {
                    return (AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.PlayState.Equals(PlayState.Playing));
                }
                catch
                {
                    return (false);
                }
            }
        }
        public Settings UISettings
        {
            get { return (_shellSettings);}
        }
        public Color UIBackground
        {
            get
            {
                if (_shellSettings.Transparent)
                {
                    return (new Color(Colors.Transparent));
                }
                else
                {
                    return (new Color(Colors.Black));
                }
            }
        }
        public Command ShowEditTextBox
        {
            get { return (_showEditTextBox); }
        }
        public string CurrentPlaylistAllStr
        {
            get
            {
                try
                {
                    return(String.Format("play list{0}",
                        MediaListLength(this._workingQueue)));
                }
                catch
                {
                    return ("play list");
                }
            }
        }
        public string CurrentPlayAllStr
        {
            get
            {
                try
                {
                    return (String.Format("play all{0}", TimeLengthInd(_contentDuration)));// MediaListLength(this.MediaSelectionList)));
                }
                catch
                {
                    return ("play all");
                }
            }
        }
        public string CurrentMediaCounterStr
        {
            get
            {
                return (String.Format("{0} of {1} media items",
                    this.MediaSelectionIndex+1, this.MediaSelectionList.Count));
            }
        }
        public Command OnScreenKeyboardActive
        {
            get { return (_onscreenKeyboardShowing); }
        }
        public Command ButtonActive
        {
            get { return (_buttonSelected); }
        }
        public bool ActivePlaylist
        {
            get { return (_playlistActive); }
        }
        public bool MediaGatheringComplete
        {
            get { return (_mediaSearchFinished); }
        }
        public Command RefreshMediaItemSelected
        {
            get { return (_refreshMediaItemSelected); }
        }
        public string CurrentMenuButtonStr
        {
            get { return (_buttonSelectedDescription); }
        }
        public string CurrentFilterStr
        {
            get
            {
                if (_appliedFilters.Count > 0)
                {
                    // First do a quick check on the type of filters in effect
                    int keywordCount = 0;
                    foreach (MediaFilter mf in _appliedFilters)
                    {
                        if (mf.Type.Equals(FilterTypeEnum.Keyword))
                        {
                            keywordCount++;
                        }
                    }
                    StringBuilder sb = new StringBuilder();
                    sb.Append("Media ");
                    StringBuilder multipleKeywords = new StringBuilder();
                    foreach (MediaFilter mf in _appliedFilters)
                    {
                        if (mf.Type.Equals(FilterTypeEnum.Year))
                        {
                            sb.AppendFormat("from the year {0} ", mf.Value);
                        }
                        if (mf.Type.Equals(FilterTypeEnum.Similar))
                        {
                            sb.AppendFormat("like '{0}' ", mf.Name);
                        }
                        if (mf.Type.Equals(FilterTypeEnum.Keyword))
                        {
                            if (keywordCount > 1)
                            {
                                multipleKeywords.AppendFormat("'{0}',", mf.Name);
                            }
                            else
                            {

                                multipleKeywords.AppendFormat("'{0}'", mf.Name);
                            }
                        }
                    }
                    if (keywordCount > 1)
                    {
                        sb.AppendFormat("with search results of {0}",
                            multipleKeywords.ToString().Substring(0, multipleKeywords.Length - 1));
                    }
                    else if(keywordCount ==1)
                    {
                        sb.AppendFormat("with search results of {0}", multipleKeywords.ToString());
                    }
                    return (sb.ToString());
                }
                else
                {
                    return (" ");
                }
                
            }
        }
        public Command MediaGatheringStateChange
        {
            get { return (_mediaGatheringCompleted); }
        }
        public Command ShowWaiting
        {
            get { return (_showWaiting); }
        }
        public Command TransitionMediaList
        {
            get { return (_transitionMediaList); }
        }
        public Command MenuDropdownShow
        {
            get { return (_menuDropdownShow); }
        }
        public Command MenuContextShow
        {
            get { return (_menuContextShow); }
        }
        public Command MediaFilterApplied
        {
            get { return (_mediaFilterApply); }
        }
        public Command MenuContextChange
        {
            get { return (_menuContextChange); }
        }
        public Choice FilterList
        {
            get {return (_filterBar);}
        }
        public Choice PopupMenuList
        {
            get { return (_popupMenuItems); }
        }
        public MediaList MediaSelectionList
        {
            get { return (_mediaSelectionItems); }
            set { _mediaSelectionItems = value; }
        }
        public Command FlipThumbs
        {
            get { return (_flipThumbs); }
        }
        public Command MediaFilterRefreshed
        {
            get { return (_mediaFilterRefreshed); }
        }
        public Command MediaFilterNew
        {
            get { return (_mediaFilterNew); }
        }
        public Command MediaSelectionNew
        {
            get { return (_mediaSelectionNew); }
        }
        public Command PopupMenuChangeState
        {
            get { return (_popupMenuChangeState); }
        }
        public Command MediaListRefreshed
        {
            get {return(_mediaListRefreshed);}
        }
        public bool MultipleInput
        {
            get { return (_popupMenuOff); }
            set
            {
                _popupMenuOff = value;
                _popupMenuChangeState.Invoke();
            }
        }
        public Int32 MediaSelectionIndex
        {
            get { return (_mediaSelectionIndex); }
            set 
            {
                _mediaSelectionIndex = value;
                _mediaSelectionNew.Invoke();
            }
        }
        public string MediaFilterCurrentInstruction
        {
            get
            {
                string returnMessage = "";
                try
                {
                    MediaFilter mf = (MediaFilter)_filterBar.Chosen;
                    if (mf.Type.Equals(FilterTypeEnum.Navigation))
                    {
                        returnMessage = "Click for previous navigation options";
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {
                        if (mf.Name.Equals("All"))
                        {
                            returnMessage = "";
                        }
                        else
                        {
                            returnMessage = "Click to filter by month";
                        }
                    }
                }
                catch { }
                return (returnMessage);
            }
        }
        public string MediaFilterCurrentDetail
        {
            get
            {
                string returnMessage = "";
                try
                {
                    MediaFilter mf = (MediaFilter)_filterBar.Chosen;
                    if (mf.Type.Equals(FilterTypeEnum.Month))
                    {
                        int lastFilterIndex = _appliedFilters.Count - 1;
                        MediaFilter lastFilter = (MediaFilter)_appliedFilters[lastFilterIndex];
                        if (lastFilter.Type.Equals(FilterTypeEnum.Year))
                        {
                            long mediaCount = _mediaTimeLines[Convert.ToInt32(lastFilter.Value)].AvailableMonths[Convert.ToInt32(mf.Value)].Count;
                            returnMessage = String.Format("{0} media items", mediaCount);
                        }
                        else
                        {
                            if (lastFilter.Type.Equals(FilterTypeEnum.Keyword))
                            {
                                returnMessage = ReturnFilterDesc();
                            }
                            else
                            {
                                returnMessage = "";
                            }
                        }
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {
                        if (mf.Name.Equals("All"))
                        {
                            long mediaCount = _filteredMediaItems.MediaItems.Count;
                            returnMessage = String.Format("{0} media items", mediaCount);
                        }
                        else
                        {
                            long mediaCount = 0;
                            foreach (MediaTimeLineMonth month in _mediaTimeLines[Convert.ToInt32(mf.Value)].AvailableMonths.Values)
                            {
                                mediaCount += month.Count;
                            }
                            returnMessage = String.Format("{0} media items", mediaCount);
                        }
                    }
                }
                catch { }
                return (returnMessage);
            }
        }
        private string ReturnFilterDesc()
        {
            if (_appliedFilters.Count > 0)
            {
                // First do a quick check on the type of filters in effect
                int keywordCount = 0;
                foreach (MediaFilter mf in _appliedFilters)
                {
                    if (mf.Type.Equals(FilterTypeEnum.Keyword))
                    {
                        keywordCount++;
                    }
                }
                StringBuilder sb = new StringBuilder();
                sb.Append("Media ");
                StringBuilder multipleKeywords = new StringBuilder();
                foreach (MediaFilter mf in _appliedFilters)
                {
                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {
                        sb.AppendFormat("from the year {0} ", mf.Value);
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Similar))
                    {
                        sb.AppendFormat("like '{0}' ", mf.Name);
                    }
                    if (mf.Type.Equals(FilterTypeEnum.Keyword))
                    {
                        if (keywordCount > 1)
                        {
                            multipleKeywords.AppendFormat("'{0}',", mf.Name);
                        }
                        else
                        {

                            multipleKeywords.AppendFormat("'{0}'", mf.Name);
                        }
                    }
                }
                if (keywordCount > 1)
                {
                    sb.AppendFormat("with search results of {0}",
                        multipleKeywords.ToString().Substring(0, multipleKeywords.Length - 1));
                }
                else if (keywordCount == 1)
                {
                    sb.AppendFormat("with search results of {0}", multipleKeywords.ToString());
                }
                return (sb.ToString());
            }
            else
            {
                return (" ");
            }

        }
        public string MediaFilterCurrentDescription
        {
            get
            {
                string returnMessage = "";
                try
                {
                    MediaFilter mf = (MediaFilter)_filterBar.Chosen;
                    if (mf.Type.Equals(FilterTypeEnum.Month))
                    {
                        int lastFilterIndex = _appliedFilters.Count - 1;
                        MediaFilter lastFilter = (MediaFilter)_appliedFilters[lastFilterIndex];
                        if (lastFilter.Type.Equals(FilterTypeEnum.Year))
                        {
                            string monthLong = _mediaTimeLines[Convert.ToInt32(lastFilter.Value)].AvailableMonths[Convert.ToInt32(mf.Value)].MonthLong;
                            returnMessage = String.Format("browse media from {0} {1}", monthLong, lastFilter.Name);
                        }
                        else
                        {
                            returnMessage = "";
                        }
                    }

                    if (mf.Type.Equals(FilterTypeEnum.All))
                    {
                        returnMessage = "browse all discovered media";
                    }

                    if (mf.Type.Equals(FilterTypeEnum.Year))
                    {
                        returnMessage = String.Format("browse media from {0}", mf.Name);
                    }
                }
                catch { }
                if (_mediaSearchFinished.Equals(false))
                {
                    if (returnMessage.Length > 0)
                    {
                        returnMessage = String.Format("{0}\n(discovering additional media...)", returnMessage);
                    }
                }

                return (returnMessage);
            }
        }
        public MediaListItem MediaSelectionCurrent
        {
            get
            {
                if (_mediaSelectionIndex.Equals(-1))
                {
                    return (new MediaListItem());
                }
                else
                {
                    return ((MediaListItem)_mediaSelectionItems[_mediaSelectionIndex]);
                }
            }
        }
        public MediaFilter CurrentFilter
        {
            get { return (_currentFilter);}
        }
        public string MediaTimeLength
        {
            get
            {
                ClipShowMetadata current = this.MediaSelectionCurrent.SourceItem;
                if (current.Duration.Equals(-1))
                {
                    return (" ");
                }
                else
                {
                    string prefix = "";
                    string suffix = "minutes";
                    TimeSpan ts;

                    if (current.IsGroupItem)
                    {
                        ts = TimeSpan.FromMilliseconds(current.Duration + current.GroupDuration);
                    }
                    else
                    {
                        ts = TimeSpan.FromMilliseconds(current.Duration);
                    }

                    if (ts.Hours.Equals(0))
                    {
                        prefix = ts.Minutes.ToString();
                        if (ts.Minutes.Equals(0))
                        {
                            prefix = ts.Seconds.ToString();
                            suffix = "seconds";
                        }
                        else
                            if (ts.Minutes.Equals(1))
                            {
                                suffix = "minute";
                            }
                    }
                    else
                    {
                        prefix = (ts.Hours * 60 + ts.Minutes).ToString();
                    }
                    string result = String.Format("|{0} {1}",
                        prefix,suffix);
                    return (result);
                }
            }
        }
        public EditTextTypeEnum EditTextType
        {
            set { _textType = value; }
            get { return (_textType); }
        }
        #endregion
    }
}
